package com.gxar.marketdelivery.domain.repo;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.gxar.marketdelivery.domain.enums.DeliveryStatus;
import com.gxar.marketdelivery.infra.dao.entity.DeliveryPlanEntity;
import com.gxar.marketdelivery.infra.dao.mapper.DeliveryPlanMapper;
import com.gxar.marketdelivery.interfaces.web.param.QueryDeliveryPlanParam;
import com.gxar.marketdelivery.interfaces.web.result.IResponseStatusMsg;
import com.gxar.marketdelivery.shared.consts.DBConsts;
import com.gxar.marketdelivery.shared.utils.AssertUtils;
import com.gxar.marketdelivery.shared.utils.CollectionUtils;
import com.gxar.marketdelivery.shared.utils.DBUtils;
import com.gxar.marketdelivery.shared.utils.DateTimeUtils;
import com.gxar.marketdelivery.shared.utils.ExtractUtils;
import com.gxar.marketdelivery.shared.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author nice
 * @version 1.0
 * @created 2023/7/20.
 */
@Service
public class DeliveryPlanRepository {

    @Autowired
    protected DeliveryPlanMapper mapper;

    public void create(DeliveryPlanEntity entity) {
        int ret = mapper.insert(entity);
        AssertUtils.isTrue(DBUtils.isSuccess(ret), IResponseStatusMsg.APIEnum.DB_ERROR, "新增投放计划失败");
    }

    public void createBatch(List<DeliveryPlanEntity> entities) {
        if (CollectionUtils.isEmpty(entities)) {
            return;
        }
        int ret = 0;
        for (DeliveryPlanEntity entity : entities) {
            ret += mapper.insert(entity);
        }
        AssertUtils.equal(ret, entities.size(), IResponseStatusMsg.APIEnum.DB_ERROR, "批量新增投放计划失败");
    }

    public void updateNotNull(DeliveryPlanEntity entity) {
        int ret = mapper.updateById(entity);
        AssertUtils.isTrue(DBUtils.isSuccess(ret), IResponseStatusMsg.APIEnum.DB_ERROR, "更新投放计划失败");
    }

    public void updatePlanStatus(Long id, Integer planStatus, String opMis) {
        UpdateWrapper<DeliveryPlanEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set(DeliveryPlanEntity.FIELD_PLAN_STATUS, planStatus);
        updateWrapper.set(DeliveryPlanEntity.FIELD_GMT_MODIFY, DateTimeUtils.now());
        updateWrapper.set(DeliveryPlanEntity.FIELD_MODIFIER, opMis);
        updateWrapper.eq(DeliveryPlanEntity.FIELD_ID, id);
        int ret = mapper.update(getById(id), updateWrapper);
        AssertUtils.isTrue(DBUtils.isSuccess(ret), IResponseStatusMsg.APIEnum.DB_ERROR, "更新投放计划状态失败");
    }

    public void deletePlan(Long id, String opMis) {
        UpdateWrapper<DeliveryPlanEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set(DeliveryPlanEntity.FIELD_STATUS, DBConsts.STATUS_UNAVAILABLE);
        updateWrapper.set(DeliveryPlanEntity.FIELD_GMT_MODIFY, DateTimeUtils.now());
        updateWrapper.set(DeliveryPlanEntity.FIELD_MODIFIER, opMis);
        updateWrapper.eq(DeliveryPlanEntity.FIELD_ID, id);
        int ret = mapper.update(getById(id), updateWrapper);
        AssertUtils.isTrue(DBUtils.isSuccess(ret), IResponseStatusMsg.APIEnum.DB_ERROR, "删除投放计划状态失败");
    }

    public void phyDelete(List<Long> ids) {
        mapper.deleteBatchIds(ids);
    }

    public DeliveryPlanEntity getById(Long id) {
        QueryWrapper<DeliveryPlanEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DeliveryPlanEntity.FIELD_STATUS, DBConsts.STATUS_AVAILABLE);
        queryWrapper.eq(DeliveryPlanEntity.FIELD_ID, id);
        return mapper.selectOne(queryWrapper);
    }

    public List<DeliveryPlanEntity> getByDeliverySetId(Long deliverySetId) {
        QueryWrapper<DeliveryPlanEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DeliveryPlanEntity.FIELD_STATUS, DBConsts.STATUS_AVAILABLE);
        queryWrapper.eq(DeliveryPlanEntity.FIELD_DELIVERY_SET_ID, deliverySetId);
        List<DeliveryPlanEntity> list = mapper.selectList(queryWrapper);
        return CollectionUtils.isNotEmpty(list) ? list : Collections.emptyList();
    }

    public Map<Long, List<DeliveryPlanEntity>> multiGetByDeliverySetIds(List<Long> deliverySetIds) {
        if (CollectionUtils.isEmpty(deliverySetIds)) {
            return Collections.emptyMap();
        }
        QueryWrapper<DeliveryPlanEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DeliveryPlanEntity.FIELD_STATUS, DBConsts.STATUS_AVAILABLE);
        queryWrapper.in(DeliveryPlanEntity.FIELD_DELIVERY_SET_ID, deliverySetIds);
        List<DeliveryPlanEntity> list = mapper.selectList(queryWrapper);
        return CollectionUtils.isEmpty(list) ?
                Collections.emptyMap() :
                CollectionUtils.toListMap(list, DeliveryPlanEntity::getId);
    }

    public List<DeliveryPlanEntity> getByDeliverySetId(Long deliverySetId, List<DeliveryStatus> planStatuses) {
        List<Integer> planStatusList = ExtractUtils.extractField(planStatuses, DeliveryStatus::getCode);
        QueryWrapper<DeliveryPlanEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DeliveryPlanEntity.FIELD_STATUS, DBConsts.STATUS_AVAILABLE);
        queryWrapper.in(DeliveryPlanEntity.FIELD_PLAN_STATUS, planStatusList);
        queryWrapper.eq(DeliveryPlanEntity.FIELD_DELIVERY_SET_ID, deliverySetId);
        List<DeliveryPlanEntity> list = mapper.selectList(queryWrapper);
        return CollectionUtils.isNotEmpty(list) ? list : Collections.emptyList();
    }

    public List<DeliveryPlanEntity> getByResSlotId(Long resSlotId) {
        QueryWrapper<DeliveryPlanEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DeliveryPlanEntity.FIELD_STATUS, DBConsts.STATUS_AVAILABLE);
        queryWrapper.eq(DeliveryPlanEntity.FIELD_RES_SLOT_ID, resSlotId);
        List<DeliveryPlanEntity> list = mapper.selectList(queryWrapper);
        return CollectionUtils.isNotEmpty(list) ? list : Collections.emptyList();
    }

    public List<DeliveryPlanEntity> getPreviewByResSlotId(Long resSlotId) {
        List<Integer> previewStatus = Lists.newArrayList(DeliveryStatus.WAIT.getCode(),
                DeliveryStatus.ONLINE.getCode());
        QueryWrapper<DeliveryPlanEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DeliveryPlanEntity.FIELD_STATUS, DBConsts.STATUS_AVAILABLE);
        queryWrapper.in(DeliveryPlanEntity.FIELD_PLAN_STATUS, previewStatus);
        queryWrapper.eq(DeliveryPlanEntity.FIELD_RES_SLOT_ID, resSlotId);
        List<DeliveryPlanEntity> list = mapper.selectList(queryWrapper);
        return CollectionUtils.isNotEmpty(list) ? list : Collections.emptyList();
    }

    public List<DeliveryPlanEntity> multiGetPreviewByResSlotId(List<Long> resSlotIds) {
        List<Integer> previewStatus = Lists.newArrayList(DeliveryStatus.WAIT.getCode(),
                DeliveryStatus.ONLINE.getCode());
        QueryWrapper<DeliveryPlanEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DeliveryPlanEntity.FIELD_STATUS, DBConsts.STATUS_AVAILABLE);
        queryWrapper.in(DeliveryPlanEntity.FIELD_PLAN_STATUS, previewStatus);
        queryWrapper.in(DeliveryPlanEntity.FIELD_RES_SLOT_ID, resSlotIds);
        List<DeliveryPlanEntity> list = mapper.selectList(queryWrapper);
        return CollectionUtils.isNotEmpty(list) ? list : Collections.emptyList();
    }


    public List<DeliveryPlanEntity> getOnlineByResSlotId(Long resSlotId) {
        QueryWrapper<DeliveryPlanEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DeliveryPlanEntity.FIELD_STATUS, DBConsts.STATUS_AVAILABLE);
        queryWrapper.eq(DeliveryPlanEntity.FIELD_PLAN_STATUS, DeliveryStatus.ONLINE.getCode());
        queryWrapper.eq(DeliveryPlanEntity.FIELD_RES_SLOT_ID, resSlotId);
        List<DeliveryPlanEntity> list = mapper.selectList(queryWrapper);
        return CollectionUtils.isNotEmpty(list) ? list : Collections.emptyList();
    }

    public Integer queryTotalCount(QueryDeliveryPlanParam param) {
        QueryWrapper<DeliveryPlanEntity> queryWrapper = buildQuery(param);
        Long cnt = mapper.selectCount(queryWrapper);
        return cnt == null ? 0 : cnt.intValue();
    }

    public List<DeliveryPlanEntity> queryPageList(QueryDeliveryPlanParam param) {
        QueryWrapper<DeliveryPlanEntity> queryWrapper = buildQuery(param);
        queryWrapper.orderByDesc(DeliveryPlanEntity.FIELD_GMT_MODIFY);
        return mapper.selectPage(new Page<>(param.getPageNow(), param.getPageSize()), queryWrapper).getRecords();
    }

    private QueryWrapper<DeliveryPlanEntity> buildQuery(QueryDeliveryPlanParam param) {
        QueryWrapper<DeliveryPlanEntity> queryWrapper = new QueryWrapper<>();
        if (param.getId() != null) {
            queryWrapper.eq(DeliveryPlanEntity.FIELD_ID, param.getId());
        }
        if (param.getResSlotId() != null) {
            queryWrapper.eq(DeliveryPlanEntity.FIELD_RES_SLOT_ID, param.getResSlotId());
        }
        if (StringUtils.isNotBlank(param.getPlanName())) {
            queryWrapper.like(DeliveryPlanEntity.FIELD_PLAN_NAME, "%" + param.getPlanName() + "%");
        }
        if (CollectionUtils.isNotEmpty(param.getPlanStatuses())) {
            queryWrapper.in(DeliveryPlanEntity.FIELD_PLAN_STATUS, param.getPlanStatuses());
        }
        if (CollectionUtils.isNotEmpty(param.getCreators())) {
            queryWrapper.in(DeliveryPlanEntity.FIELD_CREATOR, param.getCreators());
        }
        if (CollectionUtils.isNotEmpty(param.getModifiers())) {
            queryWrapper.in(DeliveryPlanEntity.FIELD_MODIFIER, param.getModifiers());
        }
        return queryWrapper;
    }
}
